package co.fitstart.admin.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dynamic;
import com.demo2do.core.utils.StringUtils;

import co.fitstart.admin.dao.CourseRoundDao;
import co.fitstart.admin.dao.CourseScheduleDao;
import co.fitstart.admin.dao.GroupDao;
import co.fitstart.admin.dao.GroupTemplateDao;
import co.fitstart.admin.entity.course.BatchDietProgram;
import co.fitstart.admin.handler.SmsSender;
import co.fitstart.admin.service.GroupService;
import co.fitstart.entity.course.round.CourseRound;
import co.fitstart.entity.course.round.CourseRoundGroup;
import co.fitstart.entity.course.round.OnlineRoundGroupStatus;
import co.fitstart.entity.course.round.RoundStatus;
import co.fitstart.entity.course.schedule.CourseSchedule;
import co.fitstart.entity.course.schedule.ScheduleStatus;
import co.fitstart.entity.courseware.CoursewareTag;
import co.fitstart.entity.courseware.dietary.Dietary;
import co.fitstart.entity.courseware.dietary.DietaryProgram;
import co.fitstart.entity.courseware.dietary.DietaryProgramTemplate;
import co.fitstart.entity.courseware.dietary.DietaryProgramType;
import co.fitstart.entity.courseware.exercise.Exercise;
import co.fitstart.entity.courseware.exercise.PlannedSchedule;
import co.fitstart.entity.courseware.fitnessgroup.BatchCourseware;
import co.fitstart.entity.courseware.fitnessgroup.BatchCoursewareType;
import co.fitstart.entity.courseware.fitnessgroup.Courseware;
import co.fitstart.entity.courseware.fitnessgroup.CoursewareEditStatus;
import co.fitstart.entity.courseware.fitnessgroup.CoursewareMovementType;
import co.fitstart.entity.courseware.fitnessgroup.CoursewareTemplate;
import co.fitstart.entity.courseware.fitnessgroup.DailyCourseware;
import co.fitstart.entity.courseware.fitnessgroup.DailyCoursewareType;
import co.fitstart.entity.courseware.fitnessgroup.FitnessGroup;
import co.fitstart.entity.courseware.fitnessgroup.SpecialCoursewareTemplate;

@Service("groupService")
public class GroupServiceImpl implements GroupService{
    
    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    @Dynamic
    private GroupDao groupDao;
    
    @Dynamic
    private CourseRoundDao courseRoundDao;
    
    @Dynamic
    private CourseScheduleDao courseScheduleDao;
    
    @Dynamic
    private GroupTemplateDao groupTemplateDao;
    
    @Autowired
    private SmsSender smsSender;
    
    @Value("#{ctx['ctx.mobile']}")
    private String ctxMobile;
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#loadBathCourseware(java.lang.Long, int)
     */
    public BatchCourseware loadBathCourseware(Long roundId, int weeks) {
        return groupDao.loadBatchCourseware(roundId, weeks);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#loadBatchCourseware(java.lang.Long, int, co.fitstart.entity.courseware.fitnessgroup.BatchCoursewareType)
     */
    public BatchCourseware loadBatchCourseware(Long roundId, int weeks, BatchCoursewareType type) {
        return groupDao.loadBatchCourseware(roundId, weeks, type);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#loadBatchCourseware(java.lang.Long)
     */
    public BatchCourseware loadBatchCourseware(Long batchId) {
        return genericDaoSupport.load(BatchCourseware.class, batchId);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#loadDailyCourseware(java.lang.Long)
     */
    public DailyCourseware loadDailyCourseware(Long dailyId) {
        return genericDaoSupport.load(DailyCourseware.class, dailyId);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#loadDailyCourseware(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware, int)
     */
    public DailyCourseware loadDailyCourseware(BatchCourseware batch, int sorting) {
        return groupDao.loadDailyCourseware(batch, sorting);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#loadCourseware(java.lang.Long)
     */
    public Courseware loadCourseware(Long coursewareId) {
        return genericDaoSupport.load(Courseware.class, coursewareId);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#rest(co.fitstart.entity.courseware.fitnessgroup.DailyCourseware)
     */
    public void rest(DailyCourseware dailyCourseware) {
        // if this dailyCourseware have coursewares delete these coursewares
        groupDao.deleteCourseware(dailyCourseware);
        
        // update dailyCourseware
        genericDaoSupport.update(dailyCourseware.changeType(DailyCoursewareType.REST));
        
        this.updateDailyStatus(dailyCourseware);
        
        this.updateBatchStatus(dailyCourseware.getBatch());
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#createCourseware(co.fitstart.entity.courseware.fitnessgroup.DailyCourseware, co.fitstart.entity.courseware.fitnessgroup.Courseware, co.fitstart.entity.courseware.fitnessgroup.CoursewareMovementType)
     */
    public void createCourseware(DailyCourseware dailyCourseware, Courseware courseware, CoursewareMovementType movementType) {
        if(dailyCourseware.getType() == null || dailyCourseware.getType().isRest()) {
            genericDaoSupport.update(dailyCourseware.changeType(DailyCoursewareType.TRAINING));
        }
        
        genericDaoSupport.save(courseware.initilization(dailyCourseware, movementType));
        
        if(courseware.getType() != null) {
            List<Courseware> coursewares = groupDao.listCourseware(dailyCourseware, courseware.getType());
            
            if(!coursewares.isEmpty() && coursewares.get(0).getRanking() != null) {
                genericDaoSupport.update(courseware.editRanking(coursewares.size()));
            }
        }
        
        this.updateDailyStatus(dailyCourseware);
        
        this.updateBatchStatus(dailyCourseware.getBatch());
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#createCoursewareGroup(co.fitstart.entity.courseware.fitnessgroup.DailyCourseware, co.fitstart.entity.courseware.fitnessgroup.FitnessGroup, co.fitstart.entity.courseware.fitnessgroup.CoursewareMovementType)
     */
    public void createCoursewareGroup(DailyCourseware dailyCourseware, FitnessGroup fitnessGroup,
            CoursewareMovementType type) {
        
        if(dailyCourseware.getType() == null || dailyCourseware.getType().isRest()) {
            genericDaoSupport.update(dailyCourseware.changeType(DailyCoursewareType.TRAINING));
        }
        
        // list this group's dailyCourseware template
        SpecialCoursewareTemplate specialCoursewareTemplate = groupTemplateDao.loadSpecialCoursewareTemplate(fitnessGroup);
        if(specialCoursewareTemplate != null) {
            List<CoursewareTemplate> coursewareTemplates = groupTemplateDao.listCoursewareTemplate(specialCoursewareTemplate);
            
            // create courseware template
            for(CoursewareTemplate template : coursewareTemplates) {
                Courseware courseware = new Courseware(template, dailyCourseware, type);
                genericDaoSupport.save(courseware);
            }
            
        }
        
        this.updateDailyStatus(dailyCourseware);
        
        this.updateBatchStatus(dailyCourseware.getBatch());
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#editCourseware(co.fitstart.entity.courseware.fitnessgroup.Courseware)
     */
    public void editCourseware(Courseware courseware) {
        genericDaoSupport.update(courseware);
        
        this.updateDailyStatus(courseware.getDaily());
        
        this.updateBatchStatus(courseware.getDaily().getBatch());
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#deleteCourseware(co.fitstart.entity.courseware.fitnessgroup.Courseware)
     */
    public void deleteCourseware(Courseware courseware) {
        genericDaoSupport.update(courseware.disable());
        
        if(courseware.getRanking() != null) {
            groupDao.riseRankingBehind(courseware.getDaily(), courseware.getType(), courseware.getRanking());
        }
        
        this.updateDailyStatus(courseware.getDaily());
        
        this.updateBatchStatus(courseware.getDaily().getBatch());
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#editDiet(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware, co.fitstart.entity.courseware.dietary.DietaryProgramTemplate)
     */
    public void editDiet(BatchCourseware batchCourseware, DietaryProgramTemplate dietaryProgramTemplate) {
        // if template has snacks save snacks first
        DietaryProgram snacks = null;
        if(dietaryProgramTemplate.getSnacks() != null) {
            DietaryProgramTemplate snacksTemplate = genericDaoSupport.load(DietaryProgramTemplate.class, dietaryProgramTemplate.getSnacks());
            snacks = new DietaryProgram(snacksTemplate, batchCourseware);
            genericDaoSupport.save(snacks);
        }
        
        DietaryProgram dietaryProgram = new DietaryProgram(dietaryProgramTemplate, batchCourseware, snacks == null ? null : snacks.getId());
        genericDaoSupport.save(dietaryProgram);
        
        this.updateBatchStatus(batchCourseware);
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#ednitSnack(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware, co.fitstart.entity.courseware.dietary.DietaryProgramTemplate, co.fitstart.entity.courseware.dietary.DietaryProgramType)
     */
    public void editSnack(BatchCourseware batchCourseware, DietaryProgramTemplate dietaryProgramTemplate, DietaryProgramType type) {
        DietaryProgram snacks = new DietaryProgram(dietaryProgramTemplate, batchCourseware);
        genericDaoSupport.save(snacks);
        
        // update diet
        DietaryProgram dietaryProgram = groupDao.loadDietaryProgram(batchCourseware, type);
        genericDaoSupport.update(dietaryProgram.editSnacks(snacks.getId()));
        
        this.updateBatchStatus(batchCourseware);
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#saveDiet(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware, co.fitstart.admin.entity.course.BatchDietProgram)
     */
    @SuppressWarnings("unlikely-arg-type")
	public void saveDiets(BatchCourseware batchCourseware, BatchDietProgram batchDietProgram) {
        this.saveDiet(batchCourseware.getDietaryPrograms().get(DietaryProgramType.BREAKFAST),
                      batchDietProgram.getBreakfastDescription(),
                      batchDietProgram.getBreakfastSnacksDescription());
        
        this.saveDiet(batchCourseware.getDietaryPrograms().get(DietaryProgramType.LUNCH),
                      batchDietProgram.getLunchDescription(),
                      batchDietProgram.getLunchSnacksDescription());
        
        this.saveDiet(batchCourseware.getDietaryPrograms().get(DietaryProgramType.DINNER),
                      batchDietProgram.getDinnerDescription(),
                      batchDietProgram.getDinnerSnacksDescription());
        
        this.updateBatchStatus(batchCourseware);
        
    }
    
    /**
     * 
     * @param dietaryProgram
     * @param mealName
     * @param mealDescription
     * @param snacksName
     * @param snacksDescription
     */
    private void saveDiet(DietaryProgram dietaryProgram, String mealDescription, String snacksDescription) {
        genericDaoSupport.update(dietaryProgram.edit(mealDescription));
        
        if(dietaryProgram.getSnacks() != null) {
            DietaryProgram breakfastSnacks = genericDaoSupport.load(DietaryProgram.class, dietaryProgram.getSnacks());
            genericDaoSupport.update(breakfastSnacks.edit(snacksDescription));
        }
    }
    
    /**
     * 
     * @param batchCourseware
     */
    private void updateBatchStatus(BatchCourseware batchCourseware) {
        if(batchCourseware.getEditStatus().isPrepare()) {
            genericDaoSupport.update(batchCourseware.editBatch());
        }
    }
    
    /**
     * 
     * @param dailyCourseware
     */
    private void updateDailyStatus(DailyCourseware dailyCourseware) {
        if(dailyCourseware.getEditStatus().isPrepare()) {
            genericDaoSupport.update(dailyCourseware.editDaily());
        }
    }
    
   /*
    * (non-Javadoc)
    * @see co.fitstart.admin.service.GroupService#linkBatchCourseware(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware)
    */
    public void linkBatchCourseware(BatchCourseware batchCourseware) {
        genericDaoSupport.update(batchCourseware.link("batch_courseware_link", null));
        
        groupDao.updateDailyStatus(batchCourseware);
        
        // send message to student
        smsSender.sendCoursewareNotice(batchCourseware.getCourseRound().getStudent().getMobile());
        
        this.finishCourseRound(batchCourseware.getCourseRound(), "weekly", 1);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#onlineRoundLink(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware, int, java.lang.String)
     */
    public void onlineRoundLink(BatchCourseware batchCourseware, int week, String coachTips) {
        String webLink = this.getWebLink(batchCourseware.getCourseRound(), week);
        genericDaoSupport.update(batchCourseware.link(webLink, coachTips));
        
        groupDao.updateDailyStatus(batchCourseware);
        
        // send message to student
        smsSender.sendCoursewareNotice(batchCourseware.getCourseRound().getStudent().getMobile());
        
        this.finishCourseRound(batchCourseware.getCourseRound(), "weekly", 1);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#onlineRoundBatchLink(java.lang.String, java.lang.String, int, java.lang.String)
     */
    public void onlineRoundBatchLink(String roundCode, String groupName, int week, String coachTips) {
        List<CourseRound> courseRounds = new ArrayList<CourseRound>();
        if(courseRoundDao.listCourseRoundGroup(roundCode).isEmpty()) {
            courseRounds = courseRoundDao.listRoundByCode(roundCode, RoundStatus.PREPARE);
        } else if(StringUtils.isEmpty(groupName)) {
            courseRounds = courseRoundDao.listUnfinishRoundByCode(new OnlineRoundGroupStatus[]{OnlineRoundGroupStatus.DISALLOW_GROUP, OnlineRoundGroupStatus.UNGROUPED}, roundCode, RoundStatus.PREPARE);
        } else {
            courseRounds = courseRoundDao.listfinishRoundByGroup(roundCode, groupName);
        }
        
        for(CourseRound courseRound : courseRounds) {
            BatchCourseware batchCourseware = groupDao.loadBatchCourseware(courseRound, week);
            if(batchCourseware != null && !batchCourseware.getEditStatus().isGenerated()) {
                this.onlineRoundLink(batchCourseware, week, coachTips);
            }
        }
        
    }
    
    /**
     * 
     * @param courseRound
     * @param week
     * @return
     */
    private String getWebLink(CourseRound courseRound, int week) {
        List<CourseRoundGroup> groups = courseRoundDao.listCourseRoundGroup(courseRound.getCode());
        CourseRoundGroup group = courseRoundDao.loadCourseRoundGroup(courseRound);
        String roundGroup = group == null ? "" : group.getName();
        boolean grouped = groups.isEmpty() ? false : true;
        return (String) (ctxMobile + "/online-courseware/entry?roundCode=" + courseRound.getCode() + 
                                     "&roundGroup=" + roundGroup + 
                                     "&grouped=" + grouped + 
                                     "&batchSorting=" + week);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#linkDailyCourseware(co.fitstart.entity.courseware.fitnessgroup.DailyCourseware)
     */
    public void linkDailyCourseware(DailyCourseware dailyCourseware) {
        // 1.update dailyCourseware
        genericDaoSupport.update(dailyCourseware.link(null));
        
        // 2. if all dailyCourseware is finish update batch
        BatchCourseware batchCourseware = dailyCourseware.getBatch();
        List<DailyCourseware> dailyCoursewares = groupDao.listDailyCourseware(batchCourseware);
        if(dailyCoursewares.isEmpty()) {
            genericDaoSupport.update(batchCourseware.link(null));
        }
        
        // 3. send message to student
        smsSender.sendCoursewareNotice(batchCourseware.getCourseRound().getStudent().getMobile());
        
        this.finishCourseRound(batchCourseware.getCourseRound(), "course", 1);
    }
    
    /**
     * 
     * @param courseRound
     * @param type
     * @param amount
     */
    private void finishCourseRound(CourseRound courseRound, String type, int amount) {
        courseRound.editPlannedAmount(type, amount);
        
        List<BatchCourseware> batchCoursewares = groupDao.listBatchCourseware(courseRound);
        if(batchCoursewares.isEmpty()) {
            courseRound.finishCourseware();
        }
        
        genericDaoSupport.update(courseRound);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#saveAll(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware)
     */
    public void saveAll(BatchCourseware batchCourseware) {
        genericDaoSupport.update(batchCourseware.saveAll());
        
        groupDao.saveAllDaily(batchCourseware);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#editCoursewareTags(java.util.List, java.util.List, java.util.List)
     */
    public void editCoursewareTags(List<Long> ids, List<String> names, List<String> descriptions) {
        for(int i=0; i<ids.size(); i++) {
            CoursewareTag coursewareTag = genericDaoSupport.load(CoursewareTag.class, ids.get(i));
            genericDaoSupport.update(coursewareTag.edit(names.get(i), descriptions.get(i)));
        }
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#loadDietary(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware)
     */
    public Dietary loadDietary(BatchCourseware batchCourseware) {
        return genericDaoSupport.searchForObject("FROM Dietary WHERE disabled = false"
                + " AND batch = :batch", "batch", batchCourseware, Dietary.class);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#loadExercise(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware)
     */
    public Exercise loadExercise(BatchCourseware batchCourseware) {
        return genericDaoSupport.searchForObject("FROM Exercise WHERE disabled = false"
                + " AND batch = :batch", "batch", batchCourseware, Exercise.class);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#listPlannedSchedule(co.fitstart.entity.courseware.fitnessgroup.BatchCourseware)
     */
    @SuppressWarnings("unchecked")
    public List<PlannedSchedule> listPlannedSchedule(BatchCourseware batchCourseware) {
        return genericDaoSupport.searchForList("FROM PlannedSchedule WHERE disabled = false and batch = :batch", "batch", batchCourseware);
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#listDietary(co.fitstart.entity.course.round.CourseRound, boolean)
     */
    public Map<Integer, Dietary> listDietary(CourseRound courseRound, boolean generated) {
        List<Dietary> dietarys = generated ? groupDao.listDietary(courseRound, CoursewareEditStatus.GENERATED) : groupDao.listDietary(courseRound);
        
        Map<Integer, Dietary> dietaryMap = new HashMap<>();
        
        if(!dietarys.isEmpty()) {
            for(Dietary dietary : dietarys) {
                dietaryMap.put(dietary.getBatch().getSorting(), dietary);
            }
        }
        
        return dietaryMap;
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#listExercise(co.fitstart.entity.course.round.CourseRound, boolean)
     */
    public Map<Integer, Exercise> listExercise(CourseRound courseRound, boolean generated) {
        List<Exercise> exercises = generated ? groupDao.listExercise(courseRound, CoursewareEditStatus.GENERATED) : groupDao.listExercise(courseRound);
        
        Map<Integer, Exercise> exerciseMap = new HashMap<>();
        
        if(!exercises.isEmpty()) {
            for(Exercise exercise : exercises) {
                exerciseMap.put(exercise.getBatch().getSorting(), exercise);
            }
        }
        
        return exerciseMap;
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#listSchedule(co.fitstart.entity.course.round.CourseRound, boolean)
     */
    public Map<Integer, Map<Integer, Map<String, Object>>> listSchedule(CourseRound courseRound, boolean generated) {
        List<PlannedSchedule> plannedSchedules = generated ? groupDao.listPlannedSchedule(courseRound, CoursewareEditStatus.GENERATED) : groupDao.listPlannedSchedule(courseRound);
        
        if(plannedSchedules.isEmpty()) {
            return null;
        } else {
            List<CourseSchedule> courseSchedules = groupDao.listCourseSchedule(courseRound, new ScheduleStatus[]{ScheduleStatus.READY, ScheduleStatus.EXPIRY, ScheduleStatus.FINISH}, 0, plannedSchedules.size());
            
            Map<Integer, Map<Integer, Map<String, Object>>> result = new HashMap<>();
            Map<Integer, Map<String, Object>> everyWeek = new HashMap<>();
            Map<String, Object> everyDay = new HashMap<>();
            int i = 0;
            int week = plannedSchedules.get(0).getBatch().getSorting();
            
            for(PlannedSchedule plannedSchedule : plannedSchedules) {
                if(plannedSchedule.getBatch().getSorting() != week) {
                    result.put(week, everyWeek);
                    everyWeek = new HashMap<>();
                    everyDay = new HashMap<>();
                    week = plannedSchedule.getBatch().getSorting();
                }
                
                everyDay.put("plan", plannedSchedule);
                if(courseSchedules.size() >= (i+1)) {
                    everyDay.put("reality", courseSchedules.get(i++));
                }
                
                everyWeek.put(plannedSchedule.getDay(), everyDay);
                everyDay = new HashMap<>();
            }
            
            result.put(week, everyWeek);
            
            return result;
        }
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#listCourseWare(co.fitstart.entity.course.round.CourseRound)
     */
    public Map<Integer, Map<String, Object>> listCourseWare(CourseRound courseRound) {
        List<CourseSchedule> courseSchedules = courseScheduleDao.listCourseSchedule(courseRound);
        
        if(courseSchedules.isEmpty()) {
            return null;
        } else {
            Map<Integer, Map<String, Object>> result = new HashMap<>();
            Map<String, Object> map;
            int i = courseSchedules.size();
            
            for(CourseSchedule courseSchedule : courseSchedules) {
                map = new HashMap<>();
                map.put("courseSchedule", courseSchedule);
                
                List<Courseware> coursewares = groupDao.listCourseware(courseSchedule);
                
                if(!coursewares.isEmpty()) {
                    map.put("coursewares", coursewares);
                }
                
                result.put(i--, map);
            }
            
            return result;
        }
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#loadCourseWare(co.fitstart.entity.course.round.CourseRound, int)
     */
    public Map<String, Object> loadCourseWare(CourseRound courseRound, int session) {
        Map<String, Object> result= new HashMap<>();
        
        List<CourseSchedule> courseSchedules = courseScheduleDao.listCourseSchedule(courseRound);
        if(!courseSchedules.isEmpty()) {
            if(session <= 0) {
                session =1;
            } else if(session > courseSchedules.size()) {
                session = courseSchedules.size();
            }
            
            CourseSchedule courseSchedule = courseSchedules.get(courseSchedules.size() - session);
            
            List<Courseware> coursewares = groupDao.listCourseware(courseSchedule);
            
            result.put("courseSchedule", courseSchedule);
            result.put("coursewares", coursewares);
        }
        
        return result;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#riseRanking(co.fitstart.entity.courseware.fitnessgroup.Courseware)
     */
    public void riseRanking(Courseware courseware) {
        this.initRanking(courseware);
        
        Courseware formerCourseware = groupDao.getCourseware(courseware.getDaily(), courseware.getType(), courseware.getRanking() - 1);
        
        if(formerCourseware != null) {
            genericDaoSupport.update(courseware.riseRanking());
            
            genericDaoSupport.update(formerCourseware.dropRanking());
        }
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.GroupService#dropRanking(co.fitstart.entity.courseware.fitnessgroup.Courseware)
     */
    public void dropRanking(Courseware courseware) {
        this.initRanking(courseware);
        
        Courseware latterCourseware = groupDao.getCourseware(courseware.getDaily(), courseware.getType(), courseware.getRanking() + 1);
        
        if(latterCourseware != null) {
            genericDaoSupport.update(courseware.dropRanking());
            
            genericDaoSupport.update(latterCourseware.riseRanking());
        }
    }
    
    /**
     * 
     * @param courseware
     */
    private void initRanking(Courseware courseware) {
        if(courseware.getRanking() == null) {
            List<Courseware> coursewares = groupDao.listCourseware(courseware.getDaily(), courseware.getType());
            int i = 1;
            
            for(Courseware eachCourseware : coursewares) {
                genericDaoSupport.update(eachCourseware.editRanking(i++));
            }
        }
    }
}
